<?php

class helper{

    static $LOG = [];
    static $lognum = 0;
    static $timedebuglist = array(0 => []);

    /**
     * 
     * @param bool $microtime
     * @return string datetime
     */
    static function now($microtime = false){
        return (string) (new DateTime)->format($microtime ? YmdHisU : YmdHis);
    }

    static function nowMicrotime(){
        return slef::now(true);
    }

    static function microtime(){
        return (new DateTime)->format("U.u");
    }

    static function clientip(){
        return (string) $_SERVER['REMOTE_ADDR'];
    }

    static function download($url){

        $filename = xSystemConfig::$originalScriptDir . "/_logs/" . 'betradar-data-' . date("YmdHis") . '.log';

        file_put_contents($filename, file_get_contents($url));

        /*
          $fp = fopen($filename, 'w+'); //This is the file where we save the    information
          $ch = curl_init(urlencode($url));
          curl_setopt($ch, CURLOPT_TIMEOUT, 50);
          curl_setopt($ch, CURLOPT_FILE, $fp); // write curl response to file
          curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
          curl_exec($ch); // get curl response
          curl_close($ch);
          fclose($fp);
         */

        return $filename;
    }

    static function LOG($class, $log = null, $execTime = null){

        self::$LOG[$class][] = [
            "time" => self::now(true),
            "ip" => helper::clientip(),
            "memory" => [
                "memory_get_usage" => memory_get_usage(),
                "memory_get_peak_usage" => memory_get_peak_usage(),
                "memory_get_peak_usage_real" => memory_get_peak_usage(true)
            ],
            "class" => $class,
            "log" => $log,
            "etime" => $execTime
        ];
        return self::$lognum++;
    }

    static function log_get($class = null){
        return $class ? self::$LOG[$class] : self::$LOGs;
    }

    static function logNum($class = null){

        return count($class ? (isset(self::$LOG[$class]) ? self::$LOG[$class] : 0) : self::$LOG);
    }

    static function log_dump($class = null){

        function draw($log){
            $log_memory = "";
            foreach($log['memory'] as $i => $v){
                $v = round($v / 1024);
                $log_memory .="<div class=\"s{$i}\">{$v}kb</div>\n";
            }
            $log['memory'] = $log_memory;
            $str = <<<xml
<table>
    <tr>
        <td class="time">{$log['time']}</td>
        <td class="ip">{$log['ip']}</td>
        <td class="class">{$log['class']}</td>
        <td class="etime">{$log['etime']}</td>
        <td class="log">{$log['log']}</td>
        <td class="memory">\n{$log['memory']}</td>
    </tr>
</table>

xml;
            return $str;
        }

        $logstr = "";
        if($class){
            if(isset(self::$LOG[$class]) && is_array(self::$LOG[$class]))
                foreach(self::$LOG[$class] as $log){
                    $logstr .= draw($log);
                }
        }
        else{
            if(is_array(self::$LOG))
                foreach(self::$LOG as $logs){
                    foreach($logs as $log){
                        $logstr .= draw($log);
                    }
                }
        }

        return $logstr;
    }

    static function timedebug($name, $name2 = null){
        if($name2){
            if(!isset(self::$timedebuglist[$name]))
                self::$timedebuglist[$name] = [];
            if(!isset(self::$timedebuglist[$name][$name2])){
                self::$timedebuglist[$name][$name2] = array();
                self::$timedebuglist[$name][$name2]['time'] = 0;
            }
            else{
                self::$timedebuglist[$name][$name2]['time']+=microtime(true) - self::$timedebuglist[$name][$name2]['markers'][count(self::$timedebuglist[$name][$name2]['markers']) - 1];
                if(isset(self::$timedebuglist[0]) && !is_array(self::$timedebuglist[0]))
                    array_unshift(self::$timedebuglist, array());
                self::$timedebuglist[0][$name][$name2] = self::$timedebuglist[$name][$name2]['time'];
            }
            if(!isset(self::$timedebuglist[$name][$name2]['markers'])){
                self::$timedebuglist[$name][$name2]['markers'] = array();
            }
            self::$timedebuglist[$name][$name2]['markers'][] = microtime(true);
        }
        else{
            if(!isset(self::$timedebuglist[$name])){
                self::$timedebuglist[$name] = array();
                self::$timedebuglist[$name]['time'] = 0;
            }
            else{
                self::$timedebuglist[$name]['time']+=microtime(true) - self::$timedebuglist[$name]['markers'][count(self::$timedebuglist[$name]['markers']) - 1];
                if(isset(self::$timedebuglist[0]) && !is_array(self::$timedebuglist[0]))
                    array_unshift(self::$timedebuglist, array());
                self::$timedebuglist[0][$name] = self::$timedebuglist[$name]['time'];
            }
            if(!isset(self::$timedebuglist[$name]['markers'])){
                self::$timedebuglist[$name]['markers'] = array();
            }
            self::$timedebuglist[$name]['markers'][] = microtime(true);
        }
    }

    static function timedebug_export(){
        return json_encode(self::$timedebuglist);
    }

    static function __esc($arr){
        foreach($arr as $i => $v){
            if(is_array($v))
                __esc($v);
            else
                $arr[$i] = db()->esc($v);
        }
        return $arr;
    }

    static function xArrayPath($data, $address, $n = 0){
        $_THIS_FUNCTION = __FUNCTION__;
        is_array($address) || $address = explode('/', trim($address, ' /'));
        return isset($address[$n]) ? self::$_THIS_FUNCTION($data[$address[$n]], $address, ++$n) : $data;
    }

    static function router($route){
        helper::timedebug("router");
        $return = [];
        foreach($route as $name => $conf){
            if(isset($conf['header']) && strlen($conf['header']))
                header($conf['header']);
            if(isset($_REQUEST[$name]) && is_string($_REQUEST[$name]) && strlen($_REQUEST[$name]) > 0){
                if(!empty($conf['list']) && in_array($_REQUEST[$name], array_keys($conf['list']))){
                    $return['require'][] = $_REQUEST[$name];
                    helper::timedebug("router: require: {$name}");
                    require_once $conf['dir'] . $_REQUEST[$name] . ".php";
                    helper::timedebug("router: require: {$name}");
                }
                else{
                    $return['ERROR'][] = "{$_REQUEST[$name]}: {$name} not exist!";
                }
            }
        }
        helper::timedebug("router");
        return $return;
    }

    static function xml2array($contents, $get_attributes = 1, $priority = 'attr'){ //http://www.bin-co.com/php/scripts/xml2array/
        if(!$contents)
            return array();

        if(!function_exists('xml_parser_create')){
            //print "'xml_parser_create()' function not found!"; 
            return array();
        }

        //Get the XML parser of PHP - PHP must have this module for the parser to work 
        $parser = xml_parser_create('');
        xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); # http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss 
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
        xml_parse_into_struct($parser, trim($contents), $xml_values);
        xml_parser_free($parser);

        if(!$xml_values)
            return; //Hmm... 


            
//Initializations 
        $xml_array = array();
        $parents = array();
        $opened_tags = array();
        $arr = array();

        $current = &$xml_array; //Refference 
        //Go through the tags. 
        $repeated_tag_index = array(); //Multiple tags with same name will be turned into an array 
        foreach($xml_values as $data){
            unset($attributes, $value); //Remove existing values, or there will be trouble 
            //This command will extract these variables into the foreach scope 
            // tag(string), type(string), level(int), attributes(array). 
            extract($data); //We could use the array by itself, but this cooler. 

            $result = array();
            $attributes_data = array();

            if(isset($value)){
                if($priority == 'tag')
                    $result = $value;
                else
                    $result['value'] = $value; //Put the value in a assoc array if we are in the 'Attribute' mode 
            }

            //Set the attributes too. 
            if(isset($attributes) and $get_attributes){
                foreach($attributes as $attr => $val){
                    if($priority == 'tag')
                        $attributes_data[$attr] = $val;
                    else
                        $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr' 
                }
            }

            //See tag status and do the needed. 
            if($type == "open"){//The starting of the tag '<tag>' 
                $parent[$level - 1] = &$current;
                if(!is_array($current) or (!in_array($tag, array_keys($current)))){ //Insert New tag 
                    $current[$tag] = $result;
                    if($attributes_data)
                        $current[$tag . '_attr'] = $attributes_data;
                    $repeated_tag_index[$tag . '_' . $level] = 1;

                    $current = &$current[$tag];
                } else{ //There was another element with the same tag name 
                    if(isset($current[$tag][0])){//If there is a 0th element it is already an array 
                        $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
                        $repeated_tag_index[$tag . '_' . $level]++;
                    }
                    else{//This section will make the value an array if multiple tags with the same name appear together 
                        $current[$tag] = array($current[$tag], $result); //This will combine the existing item and the new item together to make an array 
                        $repeated_tag_index[$tag . '_' . $level] = 2;

                        if(isset($current[$tag . '_attr'])){ //The attribute of the last(0th) tag must be moved as well 
                            $current[$tag]['0_attr'] = $current[$tag . '_attr'];
                            unset($current[$tag . '_attr']);
                        }
                    }
                    $last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
                    $current = &$current[$tag][$last_item_index];
                }
            }
            elseif($type == "complete"){ //Tags that ends in 1 line '<tag />' 
                //See if the key is already taken. 
                if(!isset($current[$tag])){ //New Key 
                    $current[$tag] = $result;
                    $repeated_tag_index[$tag . '_' . $level] = 1;
                    if($priority == 'tag' and $attributes_data)
                        $current[$tag . '_attr'] = $attributes_data;
                } else{ //If taken, put all things inside a list(array) 
                    if(isset($current[$tag][0]) and is_array($current[$tag])){//If it is already an array... 
                        // ...push the new element into that array. 
                        $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;

                        if($priority == 'tag' and $get_attributes and $attributes_data){
                            $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
                        }
                        $repeated_tag_index[$tag . '_' . $level]++;
                    }
                    else{ //If it is not an array... 
                        $current[$tag] = array($current[$tag], $result); //...Make it an array using using the existing value and the new value 
                        $repeated_tag_index[$tag . '_' . $level] = 1;
                        if($priority == 'tag' and $get_attributes){
                            if(isset($current[$tag . '_attr'])){ //The attribute of the last(0th) tag must be moved as well 
                                $current[$tag]['0_attr'] = $current[$tag . '_attr'];
                                unset($current[$tag . '_attr']);
                            }

                            if($attributes_data){
                                $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
                            }
                        }
                        $repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken 
                    }
                }
            }
            elseif($type == 'close'){ //End of tag '</tag>' 
                $current = &$parent[$level - 1];
            }
        }

        return($xml_array);
    }

}

?>
